#ifndef SEMANTICNODECLASS_H_
#define SEMANTICNODECLASS_H_

#include "SemanticNode.h"
#include "SemanticNodeEnum.h"
#include "SemanticNodeField.h"
#include "SemanticNodeMethod.h"
#include "SemanticNodeConstructor.h"
#include "SemanticNodeProperty.h"
#include "UsingDirectives.h"

#include "../syntax_tree.h"
#include "../main_container.h"

#include <string>
#include <sstream>
#include <map>
#include <vector>

extern MainContainer *compilerData;

class SemanticNodeConstructor;

class SemanticNodeClass : public SemanticNode {

private:
	/** Modifikatori klase. */
	enum ClassMod {
		CM_Public    = 0x01,
		CM_Private   = 0x02,
		CM_Protected = 0x04,
		CM_Abstract  = 0x08,
		CM_Sealed    = 0x10
	};

	/** Struktura za pohranjivanje klasa koje se nasljedjuju. */
	struct {
		std::string name;
		std::vector<std::string> templates;
	} ciInherited;

	// ovo je samo privremeno dok ne napravimo njegovu klasu ili ga ne zanemarimo
	SemanticNode* classBody;

	/** Ime klase. */
	std::string name;
	/** Using direktive. */
	UsingDirectives *usingDirectives;

	/** Podaci o modifikatorima klase. */
	char mod;

	/** Template od ove klase. */
	std::vector<std::string> templateNames;

	/** Da li ova klasa nasljedjuje od neke druge */
	bool inherited;

	/** Svi fieldovi definirani u ovoj klasi. */
	std::vector<SemanticNodeEnum *> enums;
	std::vector<SemanticNodeField *> fields;
	std::vector<SemanticNodeClass *> classes;
	std::vector<SemanticNodeConstructor *> constructors;
	std::vector<SemanticNodeMethod *> methods;
	std::vector<SemanticNodeProperty *> properties;

	/**
		* Metoda koja ispisuje izravnati template.
		*
		* @param tpl Referenca na izravnati template.
		* @return String koji predstavlja izravnati template.
		*/
	std::string writeTemplate(std::vector<std::string> &tpl);

	//friend void flattenFields(const SyntaxTreeNode *fieldNode, const SemanticNode *parent, std::map<std::string, SemanticNodeField *> &fields);

	int nameCount(std::string name);

protected:

public:
	/**
	 * Stvara novi SemanticNodeClass na temelju sintaksnog cvora i roditelja ovog semantickog cvora.
		*
		* @param syntaxNode Sintaksni cvor iz kojeg se stvara semanticki cvor.
		* @param parent Roditelj ovog semantickog cvora - ne moze biti NULL!
		*/
	SemanticNodeClass(const SyntaxTreeNode& syntaxNode, SemanticNode *parent);
	~SemanticNodeClass();

	void addConstructor(SemanticNodeConstructor *constructorNode);
	void addFields(std::vector<SemanticNodeField *> fieldNodes);
	void addMethod(SemanticNodeMethod *methodNode);
	void addProperty(SemanticNodeProperty *propertyNode);
	void addEnum(SemanticNodeEnum *enumNode);
	void addClass(SemanticNodeClass *classNode);

	std::string getName();

	bool isAbstract();
	bool isPublic();
	bool isPrivate();
	bool isProtected();
	bool isFinal();

	virtual std::string toDebugString(int tab);
};

#endif /* SEMANTICNODECLASS_H_ */
